package com.bozhong.config.common;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.bozhong.config.exception.ConfigException;
import com.bozhong.config.handle.NacosDataParserHandler;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * @author fupan
 */
@Data
@Slf4j
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ConfigSetPropertyHolder extends PropertyPlaceholderConfigurer {

	private String serverAddr;
	private String encode;
	@Builder.Default
	private String group = "DEFAULT_GROUP";
	private int timeout;
	private String endpoint;
	private String namespace;
	private String accessKey;
	private String secretKey;
	private String contextPath;
	private String clusterName;
	private String dataId;
	private ConfigService configService;
	@Builder.Default
	private String fileExtension = "properties";


	public void init() {
		try {
			this.configServiceInstance();
			this.loadAppConfigProperties();
			this.addConfigListener();
		} catch (Throwable e) {
			throw new ConfigException(e);
		}
	}

	public static String getProperty(String name) {
		return System.getProperty(name);
	}

	public void loadAppConfigProperties() {
		loadNacosData(dataId, group, fileExtension).forEach((k, v) -> {
			System.out.println(k + " = " + v);
			System.setProperty(ObjectUtil.toString(k), ObjectUtil.toString(v));
		});
	}


	private void configServiceInstance() {
		if (null != this.configService) {
		} else {
			Properties properties = new Properties();
			properties.put("serverAddr", Objects.toString(this.serverAddr, ""));
			properties.put("encode", Objects.toString(this.encode, ""));
			properties.put("namespace", Objects.toString(this.namespace, ""));
			properties.put("accessKey", Objects.toString(this.accessKey, ""));
			properties.put("secretKey", Objects.toString(this.secretKey, ""));
			properties.put("contextPath", Objects.toString(this.contextPath, ""));
			properties.put("clusterName", Objects.toString(this.clusterName, ""));
			String endpoint = Objects.toString(this.endpoint, "");
			if (endpoint.contains(":")) {
				int index = endpoint.indexOf(":");
				properties.put("endpoint", endpoint.substring(0, index));
				properties.put("endpointPort", endpoint.substring(index + 1));
			} else {
				properties.put("endpoint", endpoint);
			}

			try {
				this.configService = NacosFactory.createConfigService(properties);
			} catch (Exception var4) {
				log.error("get data from Nacos error,dataId:{}, ", dataId, var4);
			}
		}
	}

	private Map<String, Object> loadNacosData(String dataId, String group, String fileExtension) {
		String data = null;

		try {
			data = this.configService.getConfig(dataId, group, this.timeout);
			return NacosDataParserHandler.getInstance()
					.parseNacosData(data, fileExtension);
		} catch (NacosException var6) {
			log.error("get data from Nacos error,dataId:{}, ", dataId, var6);
		} catch (Exception var7) {
			log.error("parse data from Nacos error,dataId:{},data:{},", dataId, data, var7);
		}
		return new HashMap<>();
	}

	private void addConfigListener() throws NacosException {
		configService.addListener(dataId, group, new Listener() {
			@SneakyThrows
			@Override
			public void receiveConfigInfo(String configInfo) {
				NacosDataParserHandler.getInstance()
						.parseNacosData(configInfo, fileExtension)
						.forEach((k, v) -> {
							System.out.println(k + " = " + v);
							System.setProperty(ObjectUtil.toString(k), ObjectUtil.toString(v));
						});
			}

			@Override
			public Executor getExecutor() {
				return null;
			}
		});
	}
}
